package com.qiaofang.collectmanage.service.common.utils;

import com.alibaba.fastjson.JSONObject;
import com.qiaofang.collectmanage.base.configuration.CollectManageConfiguration;
import com.qiaofang.collectmanage.service.common.bean.*;
import com.qiaofang.collectmanage.service.common.constant.ConstantProperties;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
public class HttpClientUtils {
    private static final Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);

    /**
     * 从动态代理IP获取iplist
     *
     * @return
     */
    public static List<ProxyIP> getProxyIpListByUrl() {
        List<ProxyIP> proxyIPList = new ArrayList<>();
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(CollectManageConfiguration.getProxyIpListByUrl());
            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(10000)
                    .setSocketTimeout(20000)
                    .build();
            httpGet.setConfig(config);
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");
            boolean flagIp = true;
            while (flagIp) {
                response = httpClient.execute(httpGet);
                HttpEntity entity = response.getEntity();
                ProxyIpAllResponse proxyIpAllResponse = JSONObject.parseObject(EntityUtils.toString(entity, "utf-8"), ProxyIpAllResponse.class);
                if (proxyIpAllResponse.getResponseCode().equals(ResponseCode.RC_SUCCESS.getResponseCode())) {
                    proxyIPList = proxyIpAllResponse.getData();
                    if (proxyIPList.size() > 0) {
                        flagIp = false;
                    }
                } else {
                    logger.error("从代理IP池获取ip error {}:{}", proxyIpAllResponse.getResponseCode(), proxyIpAllResponse.getResponseMessage());
                }
            }
        } catch (IOException e) {
            //TODO 钉钉报警
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        if (proxyIPList.size() == 0) {
            getProxyIpListByUrl();
        }
        return proxyIPList;
    }


    public static RequestResponseInfo getPagetext(String targetUrl, String charset) {
        RequestResponseInfo requestResponseInfo = null;

        int count = 1;
        String pageText = "";
        while (count <= 3) {
            boolean isHttps = false;
            if (targetUrl.contains("https")) {
                isHttps = true;
            }
            List<ProxyIP> proxyIPList = getProxyIpListByUrl();
            int random = new Random().nextInt(proxyIPList.size());
            ProxyIP proxyIP = proxyIPList.get(random%proxyIPList.size());

            WuHttpClient wuHttpClient = new WuHttpClient(300, targetUrl, proxyIP, isHttps, charset);
            requestResponseInfo = wuHttpClient.webParseHtml(targetUrl);
            pageText = requestResponseInfo.getResponseText();

            if (StringUtils.isNotBlank(pageText) && pageText.contains("访问验证-安居客")) {
                // TODO 报警
                pageText = "";
            }
            if (StringUtils.isNotBlank(pageText)) {
                break;
            } else if (count == 3) {
                break;
            }
            count += 1;

        }
        return requestResponseInfo;
    }

    /**
     * 获取重定向的地址
     *
     * @param sourceUrl
     * @return
     */
    public static String getRedirectUrl(String sourceUrl) {
        String url = "";
        HttpGet httpGet = new HttpGet(sourceUrl);
        CloseableHttpResponse response = null;
        return url;
    }

    public static String getPageTextByProxyIp(String sourceUrl, String charset) {
        String pageText = "";
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(sourceUrl);
            List<ProxyIP> proxyIPList = getProxyIpListByUrl();
            int random = new Random().nextInt(proxyIPList.size());
            int index = 0;
            ProxyIP proxyIP = null;
            Iterator<ProxyIP> proxyIPIterator = proxyIPList.iterator();
            while (proxyIPIterator.hasNext()) {
                proxyIP = proxyIPIterator.next();
                index++;
                if (index == random) {
                    break;
                }
            }
            HttpHost proxy = new HttpHost(proxyIP.getIp(), Integer.valueOf(proxyIP.getPort()));
            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(10000)
                    .setSocketTimeout(20000)
                    .setProxy(proxy)
                    .build();
            httpGet.setConfig(config);
            response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            pageText = EntityUtils.toString(entity, charset);
        } catch (Exception e) {
            logger.info("error:{}",e);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return pageText;
    }

    public static String getPageTextByProxy(String sourceUrl, String charset) {
        int allRequestCount = 0;
        String pageText = "";
        int count = 0;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        Long start = System.currentTimeMillis();
        List<ProxyIP> proxyIPList = getProxyIpListByUrl();
        while(count<3){
            Long start1 = System.currentTimeMillis();
            try {
                httpClient = HttpClients.createDefault();
                HttpGet httpGet = new HttpGet(sourceUrl);
                int random = new Random().nextInt(proxyIPList.size());
                ProxyIP proxyIP = proxyIPList.get(random);
                HttpHost proxy = new HttpHost(proxyIP.getIp(), Integer.valueOf(proxyIP.getPort()));
                RequestConfig config = RequestConfig.custom()
                        .setConnectTimeout(2000)
                        .setSocketTimeout(3000)
                        .setCookieSpec(CookieSpecs.IGNORE_COOKIES)
                        .setProxy(proxy)
                        .build();
                httpGet.setConfig(config);
                httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");
                response = httpClient.execute(httpGet);
                HttpEntity entity = response.getEntity();
                pageText = EntityUtils.toString(entity, charset);
                logger.info("单次请求时间{}毫秒,url{},代理ip{}",(System.currentTimeMillis()-start1),sourceUrl,proxyIP.getIp());
            } catch (IOException e) {
                logger.error("调用HttpClient error delete 异常{} 失败的URL {}", e, sourceUrl);
            } finally {
                if (response != null) {
                    try {
                        response.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (null != httpClient) {
                    try {
                        httpClient.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                count++;
                allRequestCount++;
                if (StringUtils.isNotBlank(pageText)) {
                    break;
                }else if(count==3){break;}
            }
        }
        logger.info("单次循环请求时间{}毫秒,总次数{}",(System.currentTimeMillis()-start),allRequestCount);
        return pageText;
    }

    /**
     * 通过图片url获取图片中的手机号码
     *
     * @param sourceUrl
     * @return
     */
    public static String getStringByUrl(String sourceUrl, String charset) {
        String phone = "";
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(sourceUrl);
            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(10000)
                    .setSocketTimeout(20000)
                    .build();
            httpGet.setConfig(config);
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");
            response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            phone = EntityUtils.toString(entity, charset);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return phone;
    }

    public static String doHttpPost(String url, Map<String, String> map, String charset) {
        String str = "";
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(10000)
                    .setSocketTimeout(20000)
                    .build();
            httpPost.setConfig(config);
            httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");
            //设置参数
            List<NameValuePair> list = new ArrayList<>();
            Iterator iterator = map.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> elem = (Map.Entry<String, String>) iterator.next();
                list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(list));
            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            str = EntityUtils.toString(entity, charset);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return str;
    }

    public static void httpPostWithJson(JSONObject jsonObj, String url) {
        HttpPost httpPost = null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
             httpClient =  HttpClients.createDefault();
            // 设置超时时间
            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(5000)
                    .setSocketTimeout(5000)
                    .build();
            httpPost = new HttpPost(url);
            // 构造消息头
            httpPost.setConfig(config);
            // 构建消息实体
            StringEntity entity = new StringEntity(jsonObj.toString(), Charset.forName("UTF-8"));
            entity.setContentEncoding("UTF-8");
            // 发送Json格式的数据请求
            entity.setContentType("application/json");
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost);
            // 检验返回码
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (httpPost != null) {
                try {
                    httpPost.releaseConnection();
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if(httpClient!=null){
                try {
                    httpClient.close();
                }catch(Exception e){
                    e.printStackTrace();
                }
            }

        }
    }

    public static String doHttpPost(String url, Map<String, String> paramMap,  Map<String, String> headerMap, String charset) {
        String str = "";
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            if (url.contains("https")) {
                httpClient = (CloseableHttpClient) wrapClient();
            }else{
                httpClient = HttpClients.createDefault();
            }

            HttpPost httpPost = new HttpPost(url);
            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(10000)
                    .setSocketTimeout(20000)
                    .build();
            httpPost.setConfig(config);

            //设置参数
            List<NameValuePair> list = new ArrayList<>();
            Iterator iterator = paramMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> elem = (Map.Entry<String, String>) iterator.next();
                list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
            }

            Iterator iteratorHeader = headerMap.entrySet().iterator();
            while (iteratorHeader.hasNext()) {
                Map.Entry<String, String> elemHeader = (Map.Entry<String, String>) iteratorHeader.next();
                httpPost.setHeader(elemHeader.getKey(), elemHeader.getValue());
            }

            httpPost.setEntity(new UrlEncodedFormEntity(list));
            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            str = EntityUtils.toString(entity, charset);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return str;
    }

    /**
     * @Description 创建一个不进行正式验证的请求客户端对象 不用导入SSL证书
     * @return HttpClient
     */
    public static HttpClient wrapClient() {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkClientTrusted(X509Certificate[] arg0,
                                               String arg1) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] arg0,
                                               String arg1) throws CertificateException {
                }
            };
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLConnectionSocketFactory ssf = new SSLConnectionSocketFactory(
                    ctx, NoopHostnameVerifier.INSTANCE);
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(ssf).build();
            return httpclient;
        } catch (Exception e) {
            return HttpClients.createDefault();
        }
    }

    public static void main(String[] args) {
            String url = "http://192.168.2.24:8242/api/put";
            Map<String, String> tags = new HashMap<>(100);
            tags.put("appname", "采房");
            MetricInfo metricInfo = new MetricInfo();
            metricInfo.setMetric("httpClients");
            metricInfo.setTimestamp(System.currentTimeMillis());
            metricInfo.setValue(1);
            metricInfo.setTags(tags);
            httpPostWithJson((JSONObject) JSONObject.toJSON(metricInfo), url);
    }

}
